import _extends from 'babel-runtime/helpers/extends';
import _classCallCheck from 'babel-runtime/helpers/classCallCheck';
import _possibleConstructorReturn from 'babel-runtime/helpers/possibleConstructorReturn';
import _inherits from 'babel-runtime/helpers/inherits';
import React from 'react';
import PropTypes from 'prop-types';
import Pager from './Pager';
import Options from './Options';
import KEYCODE from './KeyCode';
import LOCALE from './locale/zh_CN';

function noop() {}

function isInteger(value) {
  return typeof value === 'number' && isFinite(value) && Math.floor(value) === value;
}

function defaultItemRender(page, type, element) {
  return element;
}

var Pagination = function (_React$Component) {
  _inherits(Pagination, _React$Component);

  function Pagination(props) {
    _classCallCheck(this, Pagination);

    var _this = _possibleConstructorReturn(this, _React$Component.call(this, props));

    _initialiseProps.call(_this);

    var hasOnChange = props.onChange !== noop;
    var hasCurrent = 'current' in props;
    if (hasCurrent && !hasOnChange) {
      console.warn('Warning: You provided a `current` prop to a Pagination component without an `onChange` handler. This will render a read-only component.'); // eslint-disable-line
    }

    var current = props.defaultCurrent;
    if ('current' in props) {
      current = props.current;
    }

    var pageSize = props.defaultPageSize;
    if ('pageSize' in props) {
      pageSize = props.pageSize;
    }

    _this.state = {
      current: current,
      currentInputValue: current,
      pageSize: pageSize
    };
    return _this;
  }

  Pagination.prototype.componentWillReceiveProps = function componentWillReceiveProps(nextProps) {
    if ('current' in nextProps) {
      this.setState({
        current: nextProps.current,
        currentInputValue: nextProps.current
      });
    }

    if ('pageSize' in nextProps) {
      var newState = {};
      var current = this.state.current;
      var newCurrent = this.calculatePage(nextProps.pageSize);
      current = current > newCurrent ? newCurrent : current;
      if (!('current' in nextProps)) {
        newState.current = current;
        newState.currentInputValue = current;
      }
      newState.pageSize = nextProps.pageSize;
      this.setState(newState);
    }
  };

  Pagination.prototype.componentDidUpdate = function componentDidUpdate(prevProps, prevState) {
    // When current page change, fix focused style of prev item
    // A hacky solution of https://github.com/ant-design/ant-design/issues/8948
    var prefixCls = this.props.prefixCls;

    if (prevState.current !== this.state.current && this.paginationNode) {
      var lastCurrentNode = this.paginationNode.querySelector('.' + prefixCls + '-item-' + prevState.current);
      if (lastCurrentNode && document.activeElement === lastCurrentNode) {
        lastCurrentNode.blur();
      }
    }
  };

  Pagination.prototype.getJumpPrevPage = function getJumpPrevPage() {
    return Math.max(1, this.state.current - (this.props.showLessItems ? 3 : 5));
  };

  Pagination.prototype.getJumpNextPage = function getJumpNextPage() {
    return Math.min(this.calculatePage(), this.state.current + (this.props.showLessItems ? 3 : 5));
  };

  Pagination.prototype.getJumpPrevPage = function getJumpPrevPage() {
    return Math.max(1, this.state.current - (this.props.showLessItems ? 3 : 5));
  };

  Pagination.prototype.getJumpNextPage = function getJumpNextPage() {
    return Math.min(this.calculatePage(), this.state.current + (this.props.showLessItems ? 3 : 5));
  };

  Pagination.prototype.render = function render() {
    // When hideOnSinglePage is true and there is only 1 page, hide the pager
    if (this.props.hideOnSinglePage === true && this.props.total <= this.state.pageSize) {
      return null;
    }

    var props = this.props;
    var locale = props.locale;

    var prefixCls = props.prefixCls;
    var allPages = this.calculatePage();
    var pagerList = [];
    var jumpPrev = null;
    var jumpNext = null;
    var firstPager = null;
    var lastPager = null;
    var gotoButton = null;

    var goButton = props.showQuickJumper && props.showQuickJumper.goButton;
    var pageBufferSize = props.showLessItems ? 1 : 2;
    var _state = this.state,
        current = _state.current,
        pageSize = _state.pageSize;


    var prevPage = current - 1 > 0 ? current - 1 : 0;
    var nextPage = current + 1 < allPages ? current + 1 : allPages;

    var dataOrAriaAttributeProps = Object.keys(props).reduce(function (prev, key) {
      if (key.substr(0, 5) === 'data-' || key.substr(0, 5) === 'aria-' || key === 'role') {
        prev[key] = props[key];
      }
      return prev;
    }, {});

    if (props.simple) {
      if (goButton) {
        if (typeof goButton === 'boolean') {
          gotoButton = React.createElement(
            'button',
            {
              type: 'button',
              onClick: this.handleGoTO,
              onKeyUp: this.handleGoTO
            },
            locale.jump_to_confirm
          );
        } else {
          gotoButton = React.createElement(
            'span',
            {
              onClick: this.handleGoTO,
              onKeyUp: this.handleGoTO
            },
            goButton
          );
        }
        gotoButton = React.createElement(
          'li',
          {
            title: props.showTitle ? '' + locale.jump_to + this.state.current + '/' + allPages : null,
            className: prefixCls + '-simple-pager'
          },
          gotoButton
        );
      }

      return React.createElement(
        'ul',
        _extends({
          className: prefixCls + ' ' + prefixCls + '-simple ' + props.className,
          style: props.style,
          ref: this.savePaginationNode
        }, dataOrAriaAttributeProps),
        React.createElement(
          'li',
          {
            title: props.showTitle ? locale.prev_page : null,
            onClick: this.prev,
            tabIndex: this.hasPrev() ? 0 : null,
            onKeyPress: this.runIfEnterPrev,
            className: (this.hasPrev() ? '' : prefixCls + '-disabled') + ' ' + prefixCls + '-prev',
            'aria-disabled': !this.hasPrev()
          },
          props.itemRender(prevPage, 'prev', React.createElement('a', { className: prefixCls + '-item-link' }))
        ),
        React.createElement(
          'li',
          {
            title: props.showTitle ? this.state.current + '/' + allPages : null,
            className: prefixCls + '-simple-pager'
          },
          React.createElement('input', {
            type: 'text',
            value: this.state.currentInputValue,
            onKeyDown: this.handleKeyDown,
            onKeyUp: this.handleKeyUp,
            onChange: this.handleKeyUp,
            size: '3'
          }),
          React.createElement(
            'span',
            { className: prefixCls + '-slash' },
            '\uFF0F'
          ),
          allPages
        ),
        React.createElement(
          'li',
          {
            title: props.showTitle ? locale.next_page : null,
            onClick: this.next,
            tabIndex: this.hasPrev() ? 0 : null,
            onKeyPress: this.runIfEnterNext,
            className: (this.hasNext() ? '' : prefixCls + '-disabled') + ' ' + prefixCls + '-next',
            'aria-disabled': !this.hasNext()
          },
          props.itemRender(nextPage, 'next', React.createElement('a', { className: prefixCls + '-item-link' }))
        ),
        gotoButton
      );
    }

    if (allPages <= 5 + pageBufferSize * 2) {
      for (var i = 1; i <= allPages; i++) {
        var active = this.state.current === i;
        pagerList.push(React.createElement(Pager, {
          locale: locale,
          rootPrefixCls: prefixCls,
          onClick: this.handleChange,
          onKeyPress: this.runIfEnter,
          key: i,
          page: i,
          active: active,
          showTitle: props.showTitle,
          itemRender: props.itemRender
        }));
      }
    } else {
      var prevItemTitle = props.showLessItems ? locale.prev_3 : locale.prev_5;
      var nextItemTitle = props.showLessItems ? locale.next_3 : locale.next_5;
      if (props.showPrevNextJumpers) {
        jumpPrev = React.createElement(
          'li',
          {
            title: props.showTitle ? prevItemTitle : null,
            key: 'prev',
            onClick: this.jumpPrev,
            tabIndex: '0',
            onKeyPress: this.runIfEnterJumpPrev,
            className: prefixCls + '-jump-prev'
          },
          props.itemRender(this.getJumpPrevPage(), 'jump-prev', React.createElement('a', { className: prefixCls + '-item-link' }))
        );
        jumpNext = React.createElement(
          'li',
          {
            title: props.showTitle ? nextItemTitle : null,
            key: 'next',
            tabIndex: '0',
            onClick: this.jumpNext,
            onKeyPress: this.runIfEnterJumpNext,
            className: prefixCls + '-jump-next'
          },
          props.itemRender(this.getJumpNextPage(), 'jump-next', React.createElement('a', { className: prefixCls + '-item-link' }))
        );
      }
      lastPager = React.createElement(Pager, {
        locale: props.locale,
        last: true,
        rootPrefixCls: prefixCls,
        onClick: this.handleChange,
        onKeyPress: this.runIfEnter,
        key: allPages,
        page: allPages,
        active: false,
        showTitle: props.showTitle,
        itemRender: props.itemRender
      });
      firstPager = React.createElement(Pager, {
        locale: props.locale,
        rootPrefixCls: prefixCls,
        onClick: this.handleChange,
        onKeyPress: this.runIfEnter,
        key: 1,
        page: 1,
        active: false,
        showTitle: props.showTitle,
        itemRender: props.itemRender
      });

      var left = Math.max(1, current - pageBufferSize);
      var right = Math.min(current + pageBufferSize, allPages);

      if (current - 1 <= pageBufferSize) {
        right = 1 + pageBufferSize * 2;
      }

      if (allPages - current <= pageBufferSize) {
        left = allPages - pageBufferSize * 2;
      }

      for (var _i = left; _i <= right; _i++) {
        var _active = current === _i;
        pagerList.push(React.createElement(Pager, {
          locale: props.locale,
          rootPrefixCls: prefixCls,
          onClick: this.handleChange,
          onKeyPress: this.runIfEnter,
          key: _i,
          page: _i,
          active: _active,
          showTitle: props.showTitle,
          itemRender: props.itemRender
        }));
      }

      if (current - 1 >= pageBufferSize * 2 && current !== 1 + 2) {
        pagerList[0] = React.cloneElement(pagerList[0], {
          className: prefixCls + '-item-after-jump-prev'
        });
        pagerList.unshift(jumpPrev);
      }
      if (allPages - current >= pageBufferSize * 2 && current !== allPages - 2) {
        pagerList[pagerList.length - 1] = React.cloneElement(pagerList[pagerList.length - 1], {
          className: prefixCls + '-item-before-jump-next'
        });
        pagerList.push(jumpNext);
      }

      if (left !== 1) {
        pagerList.unshift(firstPager);
      }
      if (right !== allPages) {
        pagerList.push(lastPager);
      }
    }

    var totalText = null;

    if (props.showTotal) {
      totalText = React.createElement(
        'li',
        { className: prefixCls + '-total-text' },
        props.showTotal(props.total, [(current - 1) * pageSize + 1, current * pageSize > props.total ? props.total : current * pageSize])
      );
    }
    var prevDisabled = !this.hasPrev();
    var nextDisabled = !this.hasNext();
    return React.createElement(
      'ul',
      _extends({
        className: prefixCls + ' ' + props.className,
        style: props.style,
        unselectable: 'unselectable',
        ref: this.savePaginationNode
      }, dataOrAriaAttributeProps),
      totalText,
      React.createElement(
        'li',
        {
          title: props.showTitle ? locale.prev_page : null,
          onClick: this.prev,
          tabIndex: prevDisabled ? null : 0,
          onKeyPress: this.runIfEnterPrev,
          className: (!prevDisabled ? '' : prefixCls + '-disabled') + ' ' + prefixCls + '-prev',
          'aria-disabled': prevDisabled
        },
        props.itemRender(prevPage, 'prev', React.createElement('a', { className: prefixCls + '-item-link' }))
      ),
      pagerList,
      React.createElement(
        'li',
        {
          title: props.showTitle ? locale.next_page : null,
          onClick: this.next,
          tabIndex: nextDisabled ? null : 0,
          onKeyPress: this.runIfEnterNext,
          className: (!nextDisabled ? '' : prefixCls + '-disabled') + ' ' + prefixCls + '-next',
          'aria-disabled': nextDisabled
        },
        props.itemRender(nextPage, 'next', React.createElement('a', { className: prefixCls + '-item-link' }))
      ),
      React.createElement(Options, {
        locale: props.locale,
        rootPrefixCls: prefixCls,
        selectComponentClass: props.selectComponentClass,
        selectPrefixCls: props.selectPrefixCls,
        changeSize: this.props.showSizeChanger ? this.changePageSize : null,
        current: this.state.current,
        pageSize: this.state.pageSize,
        pageSizeOptions: this.props.pageSizeOptions,
        quickGo: this.props.showQuickJumper ? this.handleChange : null,
        goButton: goButton
      })
    );
  };

  return Pagination;
}(React.Component);

Pagination.propTypes = {
  prefixCls: PropTypes.string,
  current: PropTypes.number,
  defaultCurrent: PropTypes.number,
  total: PropTypes.number,
  pageSize: PropTypes.number,
  defaultPageSize: PropTypes.number,
  onChange: PropTypes.func,
  hideOnSinglePage: PropTypes.bool,
  showSizeChanger: PropTypes.bool,
  showLessItems: PropTypes.bool,
  onShowSizeChange: PropTypes.func,
  selectComponentClass: PropTypes.func,
  showPrevNextJumpers: PropTypes.bool,
  showQuickJumper: PropTypes.oneOfType([PropTypes.bool, PropTypes.object]),
  showTitle: PropTypes.bool,
  pageSizeOptions: PropTypes.arrayOf(PropTypes.string),
  showTotal: PropTypes.func,
  locale: PropTypes.object,
  style: PropTypes.object,
  itemRender: PropTypes.func
};
Pagination.defaultProps = {
  defaultCurrent: 1,
  total: 0,
  defaultPageSize: 10,
  onChange: noop,
  className: '',
  selectPrefixCls: 'rc-select',
  prefixCls: 'rc-pagination',
  selectComponentClass: null,
  hideOnSinglePage: false,
  showPrevNextJumpers: true,
  showQuickJumper: false,
  showSizeChanger: false,
  showLessItems: false,
  showTitle: true,
  onShowSizeChange: noop,
  locale: LOCALE,
  style: {},
  itemRender: defaultItemRender
};

var _initialiseProps = function _initialiseProps() {
  var _this2 = this;

  this.savePaginationNode = function (node) {
    _this2.paginationNode = node;
  };

  this.calculatePage = function (p) {
    var pageSize = p;
    if (typeof pageSize === 'undefined') {
      pageSize = _this2.state.pageSize;
    }
    return Math.floor((_this2.props.total - 1) / pageSize) + 1;
  };

  this.isValid = function (page) {
    return isInteger(page) && page >= 1 && page !== _this2.state.current;
  };

  this.handleKeyDown = function (e) {
    if (e.keyCode === KEYCODE.ARROW_UP || e.keyCode === KEYCODE.ARROW_DOWN) {
      e.preventDefault();
    }
  };

  this.handleKeyUp = function (e) {
    var inputValue = e.target.value;
    var currentInputValue = _this2.state.currentInputValue;
    var value = void 0;

    if (inputValue === '') {
      value = inputValue;
    } else if (isNaN(Number(inputValue))) {
      value = currentInputValue;
    } else {
      value = Number(inputValue);
    }

    if (value !== currentInputValue) {
      _this2.setState({
        currentInputValue: value
      });
    }

    if (e.keyCode === KEYCODE.ENTER) {
      _this2.handleChange(value);
    } else if (e.keyCode === KEYCODE.ARROW_UP) {
      _this2.handleChange(value - 1);
    } else if (e.keyCode === KEYCODE.ARROW_DOWN) {
      _this2.handleChange(value + 1);
    }
  };

  this.changePageSize = function (size) {
    var current = _this2.state.current;
    var newCurrent = _this2.calculatePage(size);
    current = current > newCurrent ? newCurrent : current;
    // fix the issue:
    // Once 'total' is 0, 'current' in 'onShowSizeChange' is 0, which is not correct.
    if (newCurrent === 0) {
      current = _this2.state.current;
    }

    if (typeof size === 'number') {
      if (!('pageSize' in _this2.props)) {
        _this2.setState({
          pageSize: size
        });
      }
      if (!('current' in _this2.props)) {
        _this2.setState({
          current: current,
          currentInputValue: current
        });
      }
    }
    _this2.props.onShowSizeChange(current, size);
  };

  this.handleChange = function (p) {
    var page = p;
    if (_this2.isValid(page)) {
      if (page > _this2.calculatePage()) {
        page = _this2.calculatePage();
      }

      if (!('current' in _this2.props)) {
        _this2.setState({
          current: page,
          currentInputValue: page
        });
      }

      var pageSize = _this2.state.pageSize;
      _this2.props.onChange(page, pageSize);

      return page;
    }

    return _this2.state.current;
  };

  this.prev = function () {
    if (_this2.hasPrev()) {
      _this2.handleChange(_this2.state.current - 1);
    }
  };

  this.next = function () {
    if (_this2.hasNext()) {
      _this2.handleChange(_this2.state.current + 1);
    }
  };

  this.jumpPrev = function () {
    _this2.handleChange(_this2.getJumpPrevPage());
  };

  this.jumpNext = function () {
    _this2.handleChange(_this2.getJumpNextPage());
  };

  this.hasPrev = function () {
    return _this2.state.current > 1;
  };

  this.hasNext = function () {
    return _this2.state.current < _this2.calculatePage();
  };

  this.runIfEnter = function (event, callback) {
    for (var _len = arguments.length, restParams = Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
      restParams[_key - 2] = arguments[_key];
    }

    if (event.key === 'Enter' || event.charCode === 13) {
      callback.apply(undefined, restParams);
    }
  };

  this.runIfEnterPrev = function (e) {
    _this2.runIfEnter(e, _this2.prev);
  };

  this.runIfEnterNext = function (e) {
    _this2.runIfEnter(e, _this2.next);
  };

  this.runIfEnterJumpPrev = function (e) {
    _this2.runIfEnter(e, _this2.jumpPrev);
  };

  this.runIfEnterJumpNext = function (e) {
    _this2.runIfEnter(e, _this2.jumpNext);
  };

  this.handleGoTO = function (e) {
    if (e.keyCode === KEYCODE.ENTER || e.type === 'click') {
      _this2.handleChange(_this2.state.currentInputValue);
    }
  };
};

export default Pagination;